home *** CD-ROM | disk | FTP | other *** search
Text File | 1987-07-06 | 58.5 KB | 2,288 lines |
- Path: uunet!rs
- From: rs@uunet.UU.NET (Rich Salz)
- Newsgroups: comp.sources.unix
- Subject: v10i038: Interpreted Functional Programming lanuage, Part 05/07
- Message-ID: <578@uunet.UU.NET>
- Date: 7 Jul 87 23:22:51 GMT
- Organization: UUNET Communications Services, Arlington, VA
- Lines: 2277
- Approved: rs@uunet.uu.net
-
- Mod.sources: Volume 10, Number 38
- Submitted by: robison@b.cs.uiuc.edu (Arch Robison)
- Archive-name: ifp/Part05
-
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh.
- # The following files will be created:
- # interp/cache.c
- # interp/cache.h
- # interp/command.c
- # interp/convert.c
- # interp/debug.c
- # interp/dos.s
- # interp/error.c
- # interp/except.c
- # interp/file.c
- # interp/forms.c
- export PATH; PATH=/bin:$PATH
- mkdir interp
- if test -f 'interp/cache.c'
- then
- echo shar: over-writing existing file "'interp/cache.c'"
- fi
- cat << \SHAR_EOF > 'interp/cache.c'
-
- /****** cache.c *******************************************************/
- /** **/
- /** University of Illinois **/
- /** **/
- /** Department of Computer Science **/
- /** **/
- /** Tool: IFP Version: 0.5 **/
- /** **/
- /** Author: Arch D. Robison Date: May 1, 1985 **/
- /** **/
- /** Revised by: Arch D. Robison Date: July 29, 1986 **/
- /** **/
- /** Principal Investigators: Prof. R. H. Campbell **/
- /** Prof. W. J. Kubitz **/
- /** **/
- /** **/
- /**------------------------------------------------------------------**/
- /** (C) Copyright 1987 University of Illinois Board of Trustees **/
- /** All Rights Reserved. **/
- /**********************************************************************/
-
- /*
- * NOTE: Function HashOb assumes a FPfloat is either 1x or 2x the size
- * of a long.
- */
-
- #include "struct.h"
- #include "cache.h"
- #include <stdio.h>
-
- #if ECACHE
-
- CacheEntry ECache[CACHE_SIZE];
-
- CacheRec Cache [4] = {
- {0,0,0,0,"Prim"},
- {0,0,0,0,"User"},
- {0,0,0,0,"PFO"},
- {0,0,0,0,"Total"},
- };
-
- #define ArraySize(A) (sizeof(A)/sizeof(A[0]))
-
- /*
- * Print the cache statistics on stdout and clear the cache statistics tallies.
- */
- void ShowCache ()
- {
- CacheRec *C,*T= &Cache[CacheTotal];
- CacheEntry *E;
- int Tally=0;
-
- for (E=ECache; E < ArrayEnd(ECache); E++)
- if (E->EC_Fun != NULL) Tally++;
-
- printf ("%d/%d = %g full cache\n",
- Tally, ArraySize (ECache), (double) Tally / ArraySize (ECache));
-
- T->Enable = 0;
- for (C= &Cache[0]; C<&Cache[4]; C++) {
- if (C->Enable) {
- Cache[CacheTotal].Enable=1;
- printf ("%s:\t%d hits in %d looks = %g%% hit rate [%d evictions]\n",
- C->Name,C->Hits,C->Looks,
- 100.0 * C->Hits / (C->Looks ? C->Looks : 1), C->Evictions);
- T->Hits += C->Hits;
- T->Looks += C->Looks;
- T->Evictions += C->Evictions;
- C->Hits = C->Looks = C->Evictions = 0;
- }
- }
- if (!T->Enable) printf ("The cache is disabled\n");
- }
-
- #if DEBUG
- void PrintCache (Message,E)
- char *Message;
- CacheEntry *E;
- {
- printf ("ECache %s ",Message); OutObject (&E->EC_In);
- printf (" : "); OutNode (E->EC_Fun);
- printf (" -> "); OutObject (&E->EC_Out);
- printf ("\n");
- }
- #endif /* DEBUG */
-
- /*
- * HashOb
- *
- * HashOb computes an integer function (hash code) of an object.
- *
- * Input
- * X = object
- * Output
- * result = hash code
- */
- int HashOb (X)
- ObjectPtr X;
- {
- register long H;
- register ListPtr P;
-
- switch (X->Tag) {
- case BOTTOM: H = 2305; break;
- case BOOLEAN: H = X->Bool; break;
- case INT: H = X->Int * 9; break;
- case FLOAT:
- if (sizeof (FPfloat) == 2*sizeof (long))
- H = ((long *)&(X->Float))[0] + ((long *)&(X->Float))[1];
- else if (sizeof (FPfloat) == sizeof (long))
- H = ((long *)&(X->Float))[0];
- else
- fprintf (stderr,"HashOb: can't hash floats on this machine!\n");
- break;
- case STRING: H = (long) X->String; break;
- case LIST:
- H = 5298;
- for (P=X->List; P!=NULL; P=P->Next)
- H = H * 0x1243 + HashOb (&P->Val);
- break;
- case NODE: H = (long) X->Node * 5; break;
- case CODE: H = (long) X->Code.CodePtr +
- (long) X->Code.CodeParam; break;
- default:
- fprintf (stderr,"HashOb: invalid tag (%d)\n",X->Tag);
- break;
- }
- return H;
- }
-
- ClearCache () /* Clear all entries from the cache. */
- {
- CacheEntry *C;
-
- for (C=ECache+CACHE_SIZE; --C >= ECache; ) {
- RepTag (&C->EC_In, BOTTOM);
- C->EC_Fun = NULL;
- RepTag (&C->EC_Out,BOTTOM);
- }
- }
-
- InitCache () /* Initialize the cache */
- {
- register CacheEntry *E;
- CacheRec *C;
-
- printf (" (cache");
- for (C=Cache; C<&Cache[3]; C++)
- if (C->Enable) printf (" %s",C->Name);
- printf (")");
-
- for (E=ECache+CACHE_SIZE; --E >= ECache; ) {
- E->EC_In. Tag = BOTTOM;
- E->EC_Fun = NULL;
- E->EC_Out.Tag = BOTTOM;
- }
- }
-
- #endif /* ECACHE */
-
- SHAR_EOF
- if test -f 'interp/cache.h'
- then
- echo shar: over-writing existing file "'interp/cache.h'"
- fi
- cat << \SHAR_EOF > 'interp/cache.h'
-
- /****** cache.h *******************************************************/
- /** **/
- /** University of Illinois **/
- /** **/
- /** Department of Computer Science **/
- /** **/
- /** Tool: IFP Version: 0.1 **/
- /** **/
- /** Author: Arch D. Robison Date: May 1, 1985 **/
- /** **/
- /** Revised by: Arch D. Robison Date: July 29, 1986 **/
- /** **/
- /** Principal Investigators: Prof. R. H. Campbell **/
- /** Prof. W. J. Kubitz **/
- /** **/
- /** **/
- /**------------------------------------------------------------------**/
- /** (C) Copyright 1987 University of Illinois Board of Trustees **/
- /** All Rights Reserved. **/
- /**********************************************************************/
-
- #define ECACHE 0 /* Implement expression cache if defined */
-
- #if ECACHE
-
- /*
- * The expression cache can be turned on selectively for expressions with
- * primitive functions, user-defined functions, or PFOs.
- *
- * Cache[i].Enable = 0/1 to turn off/on cache for expression type i in [0..2].
- */
- #define CachePrim 0
- #define CacheUser 1
- #define CachePFO 2
- #define CacheTotal 3
-
- typedef struct {
- boolean Enable;
- int Looks; /* Number of looks into cache */
- int Hits; /* Number of successful looks */
- int Evictions; /* Number of evictions */
- char *Name; /* "Prim", "User", "PFO", etc.*/
- } CacheRec;
-
- extern CacheRec Cache[];
-
- #if DEBUG
- extern void PrintCache ();
- #endif
-
- /*
- * The expression cache is implemented as a hash table. It
- * associates outputs with <input,function> pairs.
- */
-
- #define CACHE_SIZE 1024 /* Must be power of 2 */
-
- /*
- * EC_Fun.Tag = BOTTOM iff that cache entry is empty
- */
- typedef struct {
- Object EC_In, EC_Out;
- NodePtr EC_Fun;
- } CacheEntry;
-
- extern CacheEntry ECache[];
- extern int HashOb ();
- extern void ShowCache (); /* Show cache statistics */
-
- /*
- * CheckCache
- *
- * Parameter
- * T = &Cache[i] where i is type of function to be cached.
- * A = call to "apply" with appropriate arguments.
- */
- #define CheckCache(T,A) \
- if ((T)->Enable) { \
- CacheEntry *C; \
- extern int TraceDepth; \
- \
- (T)->Looks++; \
- C = &ECache [(HashOb(InOut) + (long) F->Node) * 0x9B & CACHE_SIZE-1]; \
- if (ApplyFun == C->EC_Fun && ObEqual (InOut,&C->EC_In)) { \
- if (Debug & DebugCache) PrintCache ("Hit!",C); \
- (T)->Hits++; \
- if (Trace|SaveTrace) printf ("IBID\n"); \
- RepObject (InOut,&C->EC_Out); \
- } else { \
- if (C->EC_Fun != NULL) { \
- (T)->Evictions++; \
- if (Debug & DebugCache) PrintCache ("Evict",C); \
- } \
- C->EC_Fun = NULL; \
- RepObject (&C->EC_In,InOut); \
- {A;} \
- C->EC_Fun = F->Node; \
- RepObject (&C->EC_Out,InOut); \
- if (Debug & DebugCache) PrintCache ("Load",C); \
- } \
- } else {A;}
-
- #else
-
- #define CheckCache(T,A) {A;}
- #define ClearCache()
-
- #endif
-
- /***************************** end of cache.h ****************************/
-
- SHAR_EOF
- if test -f 'interp/command.c'
- then
- echo shar: over-writing existing file "'interp/command.c'"
- fi
- cat << \SHAR_EOF > 'interp/command.c'
-
- /****** command.c *****************************************************/
- /** **/
- /** University of Illinois **/
- /** **/
- /** Department of Computer Science **/
- /** **/
- /** Tool: IFP Version: 0.5 **/
- /** **/
- /** Author: Arch D. Robison Date: May 1, 1985 **/
- /** **/
- /** Revised by: Arch D. Robison Date: Jan 28, 1987 **/
- /** **/
- /** Principal Investigators: Prof. R. H. Campbell **/
- /** Prof. W. J. Kubitz **/
- /** **/
- /** **/
- /**------------------------------------------------------------------**/
- /** (C) Copyright 1987 University of Illinois Board of Trustees **/
- /** All Rights Reserved. **/
- /**********************************************************************/
-
- /*************************** Command Interpreter **************************/
-
-
- #include <stdio.h>
- #include <errno.h>
- #include "struct.h"
- #include "node.h"
- #include "umax.h"
- #include "inob.h"
- #include "cache.h"
- #include "stats.h"
-
- #if OPSYS==UNIX
- #include <strings.h>
- #include <sys/wait.h>
- #endif
-
- #if OPSYS==MSDOS
- #include "/usr/include/dos/spawn.h" /* Full name so lint can find it */
- #include "/usr/include/dos/string.h"
- #endif
-
- extern char EditorPath [],*EdCommand;
- extern char *getenv ();
-
- extern boolean RefCheck (); /* from apply.c */
-
- #if OPSYS==UNIX
- extern fork (),execl ();
- #endif
-
- InDesc UserIn;
-
- /*
- * ReadNode
- */
- private NodePtr ReadNode (U)
- InDesc *U;
- {
- Object S;
-
- if (!InNode (U,&S,NIL)) return NULL;
- LinkPath (&S,DEF);
- if (S.Tag == NODE) return S.Node;
- else {
- printf ("Error: ");
- OutString (S.String);
- printf (" not defined\n");
- return NULL;
- }
- }
-
- #if REFCHECK
- /*
- * ShowRefCheck
- */
- void ShowRefCheck ()
- {
- Object F;
- register InDesc *U;
-
- U = &UserIn;
- F.Tag = BOTTOM;
-
- (void) InComp (U,&F,NIL);
- (void) RefCheck ((NodePtr) NULL,&F);
- RepTag (&F,BOTTOM);
- }
- #endif
-
-
- /*
- * ShowApply
- */
- private void ShowApply (OutGraph)
- int OutGraph;
- {
- Object X,F;
- register InDesc *U;
-
- U = &UserIn;
- X.Tag = BOTTOM;
- F.Tag = BOTTOM;
- if (InObject (U,&X)) {
-
- if (!IsTok (U,":")) (void) InError (U,"colon expected");
- else {
- (void) InComp (U,&F,NIL);
- if (Debug & DebugFile) {
- printf ("Object = "); OutObject (&X); printf ("\n");
- printf ("Function = "); OutFun (&F,MaxInt); printf ("\n");
- }
-
- if (*U->InPtr) (void) InError (U,"extra character on line");
- else {
- U->InPtr++;
- ClearCache ();
- Apply (&X,&F);
- #ifdef GRAPHICS
- if (OutGraph) DrawObject (&X);
- else OutPretty (&X,0);
- #else
- OutPretty (&X,0);
- printf ("\n");
- #endif
- }
- }
- }
- RepTag (&X,BOTTOM);
- RepTag (&F,BOTTOM);
- }
-
- /*
- * ExecFile
- *
- * Execute a file
- *
- * Input
- * Prog = program to be executed
- * Arg = argument string
- */
- void ExecFile (Prog,Arg)
- char *Prog,*Arg;
- {
- if (Debug & DebugFile) printf ("ExecFile (%s,%s)\n",Prog,Arg);
- #if OPSYS==UNIX
- if (fork ()) (void) wait ((union wait *)NULL);
- else {
- if (Debug & DebugFile) printf ("prepare to flush\n");
- (void) fflush (stdout);
- execl (Prog,Prog,Arg,(char *)NULL);
- perror (Prog);
- exit (1);
- }
- #endif
- #if OPSYS==MSDOS
- if (spawnl (P_WAIT,Prog,Prog,Arg,(char *)NULL)) perror (Prog);
- #endif
- }
-
- void ExecEdit (FileName)
- char *FileName;
- {
- if (Debug & DebugFile) printf ("ExecEdit (%s)\n",FileName);
- #if OPSYS==UNIX
- ExecFile (EditorPath,FileName);
- #endif
- #if OPSYS==MSDOS
- {
- extern char *PathSplit ();
- char *T;
- T = PathSplit (FileName);
- if (T != NULL) ExecFile (EditorPath,T);
- }
- #endif
- }
-
- /*
- * EditRm
- *
- * Action depends on ``Edit'' flag:
- *
- * Edit
- * Apply the user's editor to a function or import file. If a function,
- * delete the function definition from memory. If %IMPORT file, reread it.
- *
- * !Edit
- * Remove a function definition or %IMPORT file.
- */
- private void EditRm (U,Edit)
- register InDesc *U;
- boolean Edit;
- {
- Object N;
- char Buf[MAXPATH+1];
- static char *Import = "%IMPORT";
-
- if (Debug & DebugFile) printf ("EditRm (%s,%d)\n",U->InPtr,Edit);
-
- if (IsTok (U,Import)) {
-
- if (Edit) ExecFile (EditorPath,Import);
- else
- if (unlink (Import)) perror (Import);
- DelImport (U->InDefMod);
- ReadImport (U->InDefMod);
-
- } else {
-
- N.Tag = BOTTOM;
- (void) InNode (U,&N,NIL);
- LinkPath (&N,DEF);
-
- /* Kill old source code definition */
- if (N.Tag == NODE)
- switch (N.Node->NodeType) {
- case DEF:
- RepTag (&N.Node->NodeData.NodeDef.DefCode,BOTTOM);
- break;
- case MODULE:
- break;
- }
-
- FormPath (&N,Buf,&Buf[MAXPATH]);
- RepTag (&N,BOTTOM);
- if (Edit) ExecEdit (Buf);
- else
- if (unlink (Buf)) perror (Buf);
- }
- }
-
- #if OPSYS==UNIX
- /*
- * Shell
- *
- * Execute a shell command
- */
- void Shell (U)
- register InDesc *U;
- {
- if (Debug & DebugFile) printf ("Shell: '%s'\n",U->InPtr);
- if (fork ()) (void) wait ((union wait *)NULL);
- else {
- (void) fflush (stdout);
- execl ("/bin/sh","sh","-c",U->InPtr,(char *)NULL);
- }
- }
- #endif
- #if OPSYS==MSDOS
- /*
- * ChDirToCWD
- *
- * Set DOS current working directory to IFP current working directory.
- *
- * This procedure is a necessary KLUDGE because the current directory
- * cache mechanism changes the current working directory all over the place.
- */
- void ChDirToCWD ()
- {
- char Buf[MAXPATH];
- extern char *FormNPath ();
-
- (void) FormPath (CurWorkDir,Buf,&Buf[MAXPATH]);
- chdir (Buf);
- }
-
- /*
- * Directory
- *
- * Show the current directory
- */
- void Directory (U)
- register InDesc *U;
- {
- extern char DirPath[];
-
- ChDirToCWD ();
- ExecFile (DirPath,U->InPtr);
- }
- #endif
-
- /*
- * SetDepth
- *
- * Set function printing depth used for printing.
- */
- SetDepth (U)
- register InDesc *U;
- {
- Object X;
- FPint N;
- extern int TraceDepth;
-
- X.Tag = BOTTOM;
- (void) InObject (U,&X);
- if (GetFPInt (&X,&N) || N < 0 || N > MaxInt)
- printf ("Error: depth must be integer in range 0..%d\n",MaxInt);
- else TraceDepth = N;
- }
-
-
- /*
- * SetTrace
- *
- * Set or reset function trace flags.
- */
- private void SetTrace (U)
- register InDesc *U;
- {
- NodePtr N;
- int T; /* phone home */
-
- if (IsTok (U,"on")) T=1;
- else if (IsTok (U,"off")) T=0;
- else {
- printf ("trace [on|off] f1 f2 f3 ... \n");
- return;
- }
- while (*U->InPtr) {
- N = ReadNode (U);
- if (N != NULL) {
- if (T) N->NodeData.NodeDef.DefFlags |= TRACE;
- else N->NodeData.NodeDef.DefFlags &= ~TRACE;
- } else break;
- }
- }
-
- #if DUMP
- extern void DumpNode();
- #endif
-
- void UserLoop ()
- {
- register InDesc *U;
- int N;
-
- U = &UserIn;
- while (1) {
- extern char FPprompt [], *gets();
- extern void ResetExcept();
- #if OPSYS==MSDOS
- extern char CWDCache [];
- CWDCache [0] = '\0'; /* Clear current directory cache */
- #endif
- ResetExcept ();
- if (Debug & DebugAlloc) {
- extern ListPtr FreeList;
- printf ("length (FreeList) = %ld\n",ListLength (FreeList));
- }
- printf ("%s",FPprompt);
- (void) fflush (stdout);
- InitIn (U,CurWorkDir,stdin,-1);
-
- /* Copy prompt so that error message '^' will point correctly. */
- U->InPtr += N = strlen (strcpy (U->InPtr,FPprompt));
- (void) fgets (U->InPtr, INBUFSIZE-N, stdin);
-
- if (!*U->InPtr || IsTok (U,"exit")) {
- #if OPSYS==MSDOS
- ChDirToCWD ();
- #endif
- return;
- }
- else if (IsTok (U,"depth")) SetDepth (U);
- else if (IsTok (U,"show")) ShowApply (0);
- #if HYPERCUBE
- else if (IsTok (U,"send")) {
- Object X;
- ForkFP ();
- InObject (U,&X);
- OutBinObject (&X);
- }
- #endif
- #if COMPILE
- else if (CompilerFlag && IsTok (U,"c")) Compile (U);
- #endif
- #if REFCHECK
- else if (IsTok (U,"check")) ShowRefCheck ();
- #endif
- #if ECACHE
- else if (IsTok (U,"cache")) ShowCache ();
- #endif
- #if STATS
- else if (IsTok (U,"stats")) ShowStats ();
- #endif
- else if (IsTok (U,"trace")) SetTrace (U);
- else if (IsTok (U,EdCommand)) EditRm (U,1);
- #if DUMP
- else if (IsTok (U,"dump")) DumpNode (CurWorkDir,0);
- #endif
- #ifdef GRAPHICS
- else if (IsTok (U,"graph")) ShowApply (1);
- #endif
- /* else if (IsTok (U,"test")) Test (U); */
- #if OPSYS==UNIX
- else if (IsTok (U,"rm")) EditRm (U,0);
- else Shell (U);
- #endif
- #if OPSYS==MSDOS
- else if (IsTok (U,"del")) EditRm (U,0);
- else if (IsTok (U,"dir")) Directory (U);
- #endif
- #if OPSYS==MSDOS || OPSYS==CTSS
- else printf ("Unknown command: %s\n",U->InPtr);
- #endif
- }
- }
-
-
- /************************** end of command.c **************************/
- SHAR_EOF
- if test -f 'interp/convert.c'
- then
- echo shar: over-writing existing file "'interp/convert.c'"
- fi
- cat << \SHAR_EOF > 'interp/convert.c'
-
- /****** convert.c *****************************************************/
- /** **/
- /** University of Illinois **/
- /** **/
- /** Department of Computer Science **/
- /** **/
- /** Tool: IFP Version: 0.5 **/
- /** **/
- /** Author: Arch D. Robison Date: May 1, 1985 **/
- /** **/
- /** Revised by: Arch D. Robison Date: July 2, 1986 **/
- /** **/
- /** Principal Investigators: Prof. R. H. Campbell **/
- /** Prof. W. J. Kubitz **/
- /** **/
- /** **/
- /**------------------------------------------------------------------**/
- /** (C) Copyright 1987 University of Illinois Board of Trustees **/
- /** All Rights Reserved. **/
- /**********************************************************************/
-
- /* Type conversion functions */
-
- #include <stdio.h>
- #include <ctype.h>
- #include "struct.h"
- #include "string.h"
- #include <math.h>
-
- #define BUFSIZE 80 /* Maximum length of numeric string */
-
- /*
- * GetFPInt
- *
- * Get value of FP integer.
- *
- * Input
- * X = FP object
- *
- * Output
- * *K = FPint value of X
- * result = error code: 0 = X was converted to integer *K
- * 1 = X not an integer
- * 2 = X too big
- */
- int GetFPInt (X,K)
- ObjectPtr X;
- FPint *K;
- {
- switch (X->Tag) {
- default: return 1;
- case INT: *K = X->Int; return 0;
- case FLOAT: {
- double F;
- F = X->Float;
- if (fabs (F) <= (double) FPMaxInt) {
- *K = (FPint) F;
- F -= (double) *K;
- return fabs (F) >= CompTol;
- } else return 2;
- }
- }
- }
-
- #if OPSYS==CTSS
- /*
- * IsFloat
- *
- * Determine if a string represents floating point number as defined
- * by C's atof function. This function is necessary for the CRAY
- * since there is a bug in sscanf for the CRAY.
- *
- * Input
- * S = string
- *
- * Output
- * result = true iff string represents number.
- */
- int IsFloat (S)
- register char *S;
- {
- int Digits = 0;
- if (*S == '+' || *S == '-') S++;
- while (isdigit (*S)) {
- S++;
- Digits++;
- }
- if (*S == '.')
- while (isdigit (*++S)) Digits++;
- if (!Digits) return 0;
- if (*S == '\0') return 1;
- if (*S++ != 'e') return 0;
- if (*S == '+' || *S == '-') S++;
- while (isdigit (*S)) S++;
- return *S == '\0';
- }
- #endif /* OPSYS==CTSS */
-
- /*
- * StrToFloat
- *
- * Convert object to float representation if possible.
- *
- * Input
- * *X = object
- *
- * Output
- * *X = new representation of object
- * result = 1 if *X is float, 0 otherwise.
- */
- boolean StrToFloat (X)
- ObjectPtr X;
- {
- CharPtr U;
- char Buf[BUFSIZE+1];
- double F;
- #if OPSYS!=CTSS
- char Term;
- #endif
- CPInit (&U,&X->String);
- (void) CPRead (&U,Buf,BUFSIZE);
-
- #if OPSYS==CTSS
- if (!IsFloat (Buf)) return 0;
- F = atof (Buf);
- #else
- Buf [strlen (Buf)] = '\1';
- if (2 != sscanf (Buf,"%lf%c",&F,&Term) || Term != '\1') return 0;
- #endif
- RepTag (X,FLOAT);
- X->Float = (FPfloat) F;
- return 1;
- }
-
- /*
- * GetDouble
- *
- * Output
- * result = 0 if *D is valid, 1 otherwise.
- */
- int GetDouble (X,D)
- ObjectPtr X;
- double *D;
- {
- switch (X->Tag) {
- case INT: *D = X->Int; return 0;
- case FLOAT: *D = X->Float; return 0;
- default: return 1;
- }
- }
-
-
- /****************************** end of convert.c *****************************/
- SHAR_EOF
- if test -f 'interp/debug.c'
- then
- echo shar: over-writing existing file "'interp/debug.c'"
- fi
- cat << \SHAR_EOF > 'interp/debug.c'
-
- /****** debug.c *******************************************************/
- /** **/
- /** University of Illinois **/
- /** **/
- /** Department of Computer Science **/
- /** **/
- /** Tool: IFP Version: 0.5 **/
- /** **/
- /** Author: Arch D. Robison Date: May 1, 1985 **/
- /** **/
- /** Revised by: Arch D. Robison Date: Dec 5, 1985 **/
- /** **/
- /** Principal Investigators: Prof. R. H. Campbell **/
- /** Prof. W. J. Kubitz **/
- /** **/
- /** **/
- /**------------------------------------------------------------------**/
- /** (C) Copyright 1987 University of Illinois Board of Trustees **/
- /** All Rights Reserved. **/
- /**********************************************************************/
-
-
- #include <stdio.h>
- #include "struct.h"
- #include "string.h"
-
- #if DEBUG
- int Debug = 0; /* Print debugging statements if true */
- #endif
-
- #if DUMP
- /*
- * DumpNode
- *
- * Print out node N and all its decendants.
- */
- void DumpNode (N,Indent)
- register NodePtr N;
- int Indent;
- {
- extern void OutIndent ();
-
- OutIndent (3*Indent);
- if (N == NULL) printf ("DumpNode: N = NULL\n");
- else {
- OutString (N->NodeName);
- switch (N->NodeType) {
- case NEWNODE: printf ("(new) "); break;
- case MODULE:
- printf (" module\n");
- for (N = N->NodeData.NodeMod.FirstChild; N!=NULL; N=N->NodeSib)
- DumpNode (N,Indent+1);
- break;
- case DEF:
- printf (" function");
- if (N->NodeData.NodeDef.DefFlags & TRACE)
- printf ("(trace) ");
- OutObject (&N->NodeData.NodeDef.DefCode);
- printf ("\n");
- break;
- case IMPORT:
- printf (" import");
- OutObject (&N->NodeData.NodeImp.ImpDef);
- printf ("\n");
- break;
- default:
- printf (" invalid NodeType (%x)\n",N->NodeType);
- break;
- }
- }
- }
-
- #endif /* DUMP */
-
-
- /*************************** end of debug.c *********************************/
-
- SHAR_EOF
- if test -f 'interp/dos.s'
- then
- echo shar: over-writing existing file "'interp/dos.s'"
- fi
- cat << \SHAR_EOF > 'interp/dos.s'
- ;
- ;/****** dos.s**********************************************************/
- ;/** **/
- ;/** University of Illinois **/
- ;/** **/
- ;/** Department of Computer Science **/
- ;/** **/
- ;/** Tool: IFP Version: 0.5 **/
- ;/** **/
- ;/** Author: Arch D. Robison Date: May 1, 1985 **/
- ;/** **/
- ;/** Revised by: Arch D. Robison Date: Sept 28, 1985 **/
- ;/** **/
- ;/** Principal Investigators: Prof. R. H. Campbell **/
- ;/** Prof. W. J. Kubitz **/
- ;/** **/
- ;/** **/
- ;/**------------------------------------------------------------------**/
- ;/** (C) Copyright 1987 University of Illinois Board of Trustees **/
- ;/** All Rights Reserved. **/
- ;/**********************************************************************/
-
- ;/***** Assembly Language Routines for MS-DOS Implementation of IFP *****/
-
- TITLE dos
-
- PUBLIC _StackCheck, _SetCBrk
- EXTRN __chkstk:FAR
-
- DOS_TEXT SEGMENT BYTE PUBLIC 'CODE'
-
-
- ASSUME CS: DOS_TEXT
- ;
- ; SetCBrk
- ;
- ; Set control-C trapping for any DOS call.
- ;
- _SetCBrk PROC FAR
- mov ax,3301H
- mov dl,01H
- int 21H
- ret
- _SetCBrk ENDP
-
- ;
- ; StackCheck
- ;
- ; Check if there is enough room on the stack and check for break signal
- ;
- _StackCheck PROC FAR
- push bp
- mov bp,sp
- mov ax,64H
- call FAR PTR __chkstk
- push es
- mov ah,2FH
- int 21H ; Dummy GET_DTA to look for control-C
- pop es
- mov sp,bp
- pop bp
- ret
- _StackCheck ENDP
-
- DOS_TEXT ENDS
- END
-
- ;/************************** end of dos.s **************************/
- SHAR_EOF
- if test -f 'interp/error.c'
- then
- echo shar: over-writing existing file "'interp/error.c'"
- fi
- cat << \SHAR_EOF > 'interp/error.c'
-
- /****** error.c *******************************************************/
- /** **/
- /** University of Illinois **/
- /** **/
- /** Department of Computer Science **/
- /** **/
- /** Tool: IFP Version: 0.5 **/
- /** **/
- /** Author: Arch D. Robison Date: May 1, 1985 **/
- /** **/
- /** Revised by: Arch D. Robison Date: Sept 8, 1986 **/
- /** **/
- /** Principal Investigators: Prof. R. H. Campbell **/
- /** Prof. W. J. Kubitz **/
- /** **/
- /** **/
- /**------------------------------------------------------------------**/
- /** (C) Copyright 1987 University of Illinois Board of Trustees **/
- /** All Rights Reserved. **/
- /**********************************************************************/
-
- /************************ Error Message Routines **********************/
-
- #include <stdio.h>
- #include <ctype.h>
- #include "struct.h"
- #include "node.h"
- #include "umax.h"
- #include "inob.h"
-
- /* Some common error messages */
-
- char ArgNotSeq[] = "not a sequence",
- ArgSeqOb [] = "must be <sequence object>",
- ArgObSeq [] = "must be <object sequence>",
- ArgNull [] = "empty sequence",
- ArgBottom[] = "argument is ?";
-
- /*
- * PrintErr
- *
- * Check if error message should be printed. Error messages are not printed if
- * the argument is BOTTOM (in which case the error has already been noted), or
- * SysStop is set (the user has interrupted execution).
- *
- * Input
- * InOut = argument to function
- *
- * Output
- * result = true iff error message should be printed
- */
- boolean PrintErr (InOut)
- ObjectPtr InOut;
- {
- return InOut->Tag != BOTTOM && !SysStop;
- }
-
- /*
- * FormError
- *
- * Print PFO error message.
- *
- * Input
- * InOut = input to form
- * Message = error message
- * N = offended form's index in FormTable
- * P = form parameter list
- */
- void FormError (InOut,Message,N,P)
- ObjectPtr InOut;
- char *Message;
- int N;
- ListPtr P;
- {
- extern int TraceDepth;
-
- if (PrintErr (InOut)) {
- LineWait ();
- OutForm (FormTable[N].FormNode,P,TraceDepth);
- printf (": %s\n",Message);
- OutObject (InOut);
- printf ("\n");
- LineSignal ();
- }
- RepTag (InOut,BOTTOM);
- }
-
- /*
- * FunError
- *
- * Print primitive function error.
- *
- * Input
- * Message = error message
- * InOut = offending object
- * ApplyFun {global} = offended function
- */
- void FunError (Message,InOut)
- char *Message;
- ObjectPtr InOut;
- {
- if (PrintErr (InOut)) {
- LineWait ();
- printf ("\n");
- OutNode (ApplyFun);
- printf (": %s\n",Message);
- OutObject (InOut);
- printf ("\n");
- LineSignal ();
- }
- RepTag (InOut,BOTTOM);
- }
-
- /*
- * DefError
- *
- * Print definition error display.
- *
- * Input
- * Caller = calling node
- * F = name of erroneous function
- * Message = error message to print
- */
- void DefError (Caller,F,Message)
- NodePtr Caller;
- ObjectPtr F;
- char *Message;
- {
- LineWait ();
- OutObject (F);
- if (Caller != NULL) {
- printf (" (from ");
- OutNode (Caller);
- printf (")");
- }
- printf (": %s\n",Message);
- LineSignal ();
- }
-
- /*
- * IntError
- *
- * Print internal error message.
- *
- * Input
- * Message = error message
- */
- void IntError (Message)
- char *Message;
- {
- fprintf (stderr,"\nINTERNAL ERROR (%s)\n",Message);
- if (Debug) abort ();
- SysError = INTERNAL;
- }
-
- /*
- * InError
- *
- * Print input error message.
- *
- * Input
- * F = input descriptor
- * Message = error message
- *
- * Output
- * result = 0
- */
- int InError (F,Message)
- InDesc *F;
- char *Message;
- {
- char *S;
-
- if (F->ComLevel > 0) Message = "open comment";
- printf ("Input error");
- if (F->InLineNum >= 0) {
- printf (" in ");
- OutNode (F->InDefMod);
- printf ("/");
- if (F->InDefFun != NULL) OutString (F->InDefFun);
- else printf ("%IMPORT");
- printf (" on line %d:\n%s",F->InLineNum,F->InBuf);
- if (F->InBuf[strlen (F->InBuf)-1] != '\n') printf ("\n");
- } else printf ("\n");
- for (S=F->InBuf; S<F->InPtr; S++)
- printf ("%c", isspace (*S) ? *S : ' ');
- printf ("^\n%s\n",Message);
- return F->ComLevel = 0;
- }
-
- /****************************** end of error.c *******************************/
-
- SHAR_EOF
- if test -f 'interp/except.c'
- then
- echo shar: over-writing existing file "'interp/except.c'"
- fi
- cat << \SHAR_EOF > 'interp/except.c'
-
- /****** except.c ******************************************************/
- /** **/
- /** University of Illinois **/
- /** **/
- /** Department of Computer Science **/
- /** **/
- /** Tool: IFP Version: 0.5 **/
- /** **/
- /** Author: Arch D. Robison Date: May 1, 1985 **/
- /** **/
- /** Revised by: Arch D. Robison Date: Dec 5, 1985 **/
- /** **/
- /** Principal Investigators: Prof. R. H. Campbell **/
- /** Prof. W. J. Kubitz **/
- /** **/
- /** **/
- /**------------------------------------------------------------------**/
- /** (C) Copyright 1987 University of Illinois Board of Trustees **/
- /** All Rights Reserved. **/
- /**********************************************************************/
-
- /************************* Exception Handlers *************************/
-
- #include <stdio.h>
- #include "struct.h"
- #include "umax.h"
-
- #if OPSYS!=CTSS
- #include <signal.h>
- #endif
-
- /*
- * There are currently two exceptions which must be dealt with.
- *
- * 1. Interpreter (system) errors, e.g. out of memory
- * These are indicated by setting the variable 'SysError' to the
- * appropriate non-zero value. The values are listed in struct.h
- *
- * 2. User interrupts, i.e. ctrl-C.
- * These are counted by the variable SysStop.
- *
- * 0 = process normally
- * 1 = stop processing and print back trace
- * 2 = return to top level without printing back trace
- */
- short SysError = 0; /* An error occurred if SysError != 0 */
- short SysStop = 0;
-
- #if OPSYS!=CTSS
- private int SetStop ()
- {
- SysStop++;
- (void) signal (SIGINT,SetStop);
- }
- #endif OPSYS!=CTSS
-
- /*
- * ResetExcept
- *
- * Reset exception handling to normal state.
- */
- void ResetExcept ()
- {
- extern int UDump();
- SysError = 0;
- SysStop = 0;
- #if OPSYS!=CTSS
- (void) signal (SIGINT,SetStop);
- #endif
- #if OPSYS==DOS
- SetCBrk ();
- #endif
- }
-
- SHAR_EOF
- if test -f 'interp/file.c'
- then
- echo shar: over-writing existing file "'interp/file.c'"
- fi
- cat << \SHAR_EOF > 'interp/file.c'
-
- /****** file.c ********************************************************/
- /** **/
- /** University of Illinois **/
- /** **/
- /** Department of Computer Science **/
- /** **/
- /** Tool: IFP Version: 0.5 **/
- /** **/
- /** Author: Arch D. Robison Date: May 1, 1985 **/
- /** **/
- /** Revised by: Arch D. Robison Date: June 22, 1986 **/
- /** **/
- /** Principal Investigators: Prof. R. H. Campbell **/
- /** Prof. W. J. Kubitz **/
- /** **/
- /** **/
- /**------------------------------------------------------------------**/
- /** (C) Copyright 1987 University of Illinois Board of Trustees **/
- /** All Rights Reserved. **/
- /**********************************************************************/
-
-
- #include <stdio.h>
- #include "struct.h"
- #include "string.h"
- #include "node.h"
- #include "umax.h"
- #include "inob.h"
-
- extern char *strcpy (),*strcat (),*getenv ();
-
- /*------------------------- Operating System Constants --------------------*
- *
- * Operating System Constants
- *
- * PATH_SEPARATOR = separator used for file names
- * EDITOR = path to editor
- * EdCommand = IFP command to invoke EDITOR
- *
- * Even operating systems without hierarchical file systems must
- * define a PATH_SEPARATOR, which is used still used internally.
- *
- * In the case of CTSS, we also have a constant USER_PATH. This
- * a fictious path to the user's current directory.
- */
-
- #if OPSYS==UNIX
- #define PATH_SEPARATOR '/'
- #define EDITOR "/bin/vi"
- char *EdCommand;
- #endif
-
- #if OPSYS==MSDOS
- #define PATH_SEPARATOR '\\'
- #define EDITOR "c:ed.exe"
- char *EdCommand = "ed";
- char DirPath [MAXPATH+1] = "c:dir.exe";
- #endif
-
- #if OPSYS==CTSS
- #define PATH_SEPARATOR '/'
- #define EDITOR "fred"
- char *EdCommand = "fred";
- #define USER_PATH "/usr"
- #endif
-
- /*-------------------- end of Operating System Constants --------------------*/
-
- char RootPath [MAXPATH+1] = ""; /* Path to IFP's root */
-
- char EditorPath [MAXPATH+1] = EDITOR; /* value is default */
-
- char FPprompt[16] = "ifp> "; /* value is default */
- NodePtr CurWorkDir = NULL; /* Current working directory node */
-
- /********************** Operating system file interface ***********************/
-
- /*
- * PathTail
- *
- * Return the last component in a path name.
- * Returns pointer to "" if error occurs.
- */
- private char *PathTail (Path)
- char *Path;
- {
- register char *T;
-
- if (*Path == PATH_SEPARATOR) Path++;
- while (*Path) {
- for (T = Path; *T++ != PATH_SEPARATOR; )
- if (!*T) return Path;
- Path = T;
- }
- return Path;
- }
-
- /*------------------------------ fopen hacks ------------------------------
- *
- * Both MSDOS and CTSS have problems with hierarchical file structure.
- * Thus we have to redefine the standard UNIX function "fopen" to allow
- * for these operating system's quirks.
- */
- #if OPSYS==MSDOS
-
- /*
- * We try to keep track of the current directory in CWDCache so we can avoid
- * superfluous calls to chdir. Set the 0th character to '\0' to empty the
- * cache.
- */
- char CWDCache [MAXPATH] = "";
-
- /*
- * PathSplit
- *
- * Split a pathname into its directory and file parts.
- * Change directory to directory part.
- *
- * Input
- * PathName = pathname
- *
- * Output
- * NULL if error occurs, pointer to file name otherwise.
- */
- char *PathSplit (PathName) /* also used by command.c */
- char *PathName;
- {
- register char *S,*T;
- register int R;
-
- T = PathTail (PathName);
- if (T != &PathName [1]) {
- T[-1] = '\0';
- S = PathName; /* Break string at path separator */
- } else S = "\\";
- if (strcmp (S,CWDCache)) {
- R = chdir (S);
- if (Debug & DebugFile) printf ("cache load: %d = ChDir (%s) for %s\n",R,S,T);
- (void) strcpy (CWDCache,S);
- } else {
- if (Debug & DebugFile) printf ("cache HIT!\n");
- R = 0;
- }
- T[-1] = PATH_SEPARATOR; /* Replace path separator */
- return R ? NULL : T;
- }
-
- /*
- * DOSfopen
- *
- * Works as =`fopen' should. The old Lattice C `fopen' would not take
- * pathnames. Even though the new compiler's will allow long names,
- * the fake fopen can take advantage of the current directory cache.
- */
- private FILE *DOSfopen (FileName,Mode)
- char *FileName,*Mode;
- {
- char *T;
-
- return (T = PathSplit (FileName)) != NULL ? fopen (T,Mode) : NULL;
- }
-
- #define fopen DOSfopen
-
- #endif /* OPSYS==MSDOS */
-
- #if OPSYS==CTSS
- /*
- * CTSSfopen
- *
- * Tries for fake a real fopen. CTSS does not support hierarchical file
- * structures, so CTSSfopen takes the tail of the path as the file name.
- */
- private FILE *CTSSfopen (FileName,Mode)
- char *FileName,*Mode;
- {
- register char *T;
-
- if (Debug & DebugFile) printf ("CTSSfopen (%s,%s)\n",FileName,Mode);
- T = PathTail (FileName);
- if (T == &FileName[1]) return NULL;
- else {
- T[-1] = '\0';
- if (strcmp (FileName,USER_PATH)) return NULL;
- else {
- if (Debug & DebugFile) printf ("fopen (%s,%s)\n",T,Mode);
- return fopen (T,Mode);
- }
- }
- }
- #define fopen CTSSfopen
-
- #endif /* OPSYS==CTSS */
-
- /*---------------------------- end of fopen hacks ----------------------------*/
-
- /*
- * FormNPath
- *
- * Create the pathname for a given node.
- *
- * Input
- * N = pointer to node
- * PathLim = pointer to end of PathName buffer
- *
- * Output
- * Pathname for node
- */
- char *FormNPath (N,PathName,PathLim)
- register NodePtr N;
- char PathName[];
- register char *PathLim;
- {
- CharPtr U;
- register char *T;
-
- if (N->NodeParent == NULL) {
- (void) strcpy (PathName,RootPath);
- return &PathName [strlen (PathName)];
- } else {
- T = FormNPath (N->NodeParent,PathName,PathLim);
- if (T==NULL) return NULL;
- else {
- *T++ = PATH_SEPARATOR;
- CPInit (&U,&N->NodeName);
- (void) CPRead (&U,T,PathLim-T);
- #if OPSYS==UNIX
- T += strlen (T);
- #endif
- #if OPSYS==MSDOS || OPSYS==CTSS
- /* DOS and CTSS names limited to 8 characters */
- {
- int L;
- if ((L = strlen (T)) > 8) L = 8;
- *(T += L) = '\0';
- }
- #endif
- if (!CPRead (&U,T,PathLim-T)) return T;
- else return NULL; /* U should be empty */
- }
- }
- }
-
-
- /*
- * FormPath
- *
- * Make UNIX or DOS pathname for node
- *
- * Input
- * N = node or path list
- * PathName = buffer to put pathname in.
- * PathLim = pointer to end of buffer
- *
- * Output
- * PathName = pathname if successful
- */
- void FormPath (N,PathName,PathLim)
- register ObjectPtr N;
- char PathName[];
- char *PathLim;
- {
- register char *T;
- CharPtr U;
- register ListPtr P;
- register int K;
-
- switch (N->Tag) {
-
- case LIST:
- (void) strcpy (PathName,RootPath);
- K = strlen (PathName);
- PathLim -= K;
- T = &PathName [K];
- for (P = N->List; P!=NULL; P=P->Next) {
- if (P->Val.Tag != STRING) return;
- else {
- CPInit (&U,&P->Val.String);
- (void) CPRead (&U,T,PathLim-PathName);
- #if OPSYS==UNIX
- T += strlen (T);
- #endif
- #if OPSYS==MSDOS || OPSYS==CTSS
- /* DOS names are limited to 8 characters */
- if ((K = strlen (T)) > 8) K = 8;
- *(T += K) = '\0';
- #endif
- /* T should always be <= PathLim */
- if (T >= PathLim) return;
- }
- }
- break;
-
- case NODE:
- (void) FormNPath (N->Node,PathName,PathLim);
- break;
-
- default:
- break;
- }
- }
-
- /*
- * ReadDef
- *
- * Read a definition node. The definition node tag must be BOTTOM upon entry
- * when running UMAX.
- *
- * Input
- * Caller = pointer to DEF node of caller
- * Fun = object with tag NODE.
- */
- void ReadDef (Caller,Fun)
- NodePtr Caller;
- ObjectPtr Fun;
- {
- NodePtr N;
- char FileName[MAXPATH];
- FILE *DefFile;
- InDesc F;
- int C;
-
-
- if (NULL == FormNPath (N=Fun->Node,FileName,&FileName[MAXPATH]))
- DefError (Caller,Fun,"invalid name for function");
- else
- while (NULL != (DefFile = fopen (FileName,"r"))) {
- InitIn (&F,N->NodeParent,DefFile,0);
- C = InDef (&F,N->NodeName,&N->NodeData.NodeDef.DefCode);
- (void) fclose (F.InFile);
- if (C) goto exit;
- printf ("Do you wish to edit %s ? ",FileName + strlen (RootPath));
- while (1) {
- for (C = getchar (); getchar ()!='\n';) continue;
- if (C == 'y') {
- ExecEdit (FileName);
- break;
- }
- if (C == 'n') goto exit;
- printf ("Respond with y or n\n");
- }
- }
- exit:;
- }
-
- /*
- * ReadImport
- *
- * Read the import file for a module node.
- *
- * Input
- * M = pointer to module node
- */
- void ReadImport (M)
- NodePtr M;
- {
- char *T;
- char FileName[MAXPATH];
- FILE *ImpFile;
- InDesc F;
-
- if (NULL != (T = FormNPath (M,FileName,&FileName[MAXPATH]))) {
- *T++ = PATH_SEPARATOR;
- (void) strcpy (T,"%IMPORT");
- if (NULL != (ImpFile = fopen (FileName,"r"))) {
- InitIn (&F,M,ImpFile,0);
- InImport (&F,M);
- (void) fclose (ImpFile);
- }
- }
- }
-
- #if OPSYS!=CTSS
- /*
- * EnvGet
- *
- * Get value for environment variable.
- *
- * Input
- * Key = enviroment variable name
- * Value = default value for variable
- * ValLim = length of Value buffer
- *
- * Output
- * Value = value of enviroment variable, or default if not found.
- */
- void EnvGet (Key,Value,ValLim)
- char *Key,*Value;
- int ValLim;
- {
- char *V;
-
- V = getenv (Key);
- if (V != NULL)
- if (strlen (V) < ValLim) (void) strcpy (Value,V);
- else fprintf (stderr,"Error: %s in enviroment is longer than %d\n",
- Key,MAXPATH-3);
- }
-
-
- /*
- * CWDGet
- *
- * Find pathname of current working directory (relative to FP root).
- *
- * Input
- * PathLim = length of Path buffer (used by PCAT versions only)
- *
- * Output
- * result = 1 if valid FP path, 0 otherwise
- * Path = FP pathname if valid, undefined otherwise
- */
- boolean CWDGet (Path,PathLim)
- register char *Path;
- int PathLim;
- {
- #ifdef PCAT
- extern char *getcwd ();
- if (!getcwd (Path,PathLim-2)) return 0;
- #else
- #if S9000
- extern FILE *popen ();
- FILE *F; /* S9000 Xenix has no getwd! */
- F = popen ("/bin/pwd","r");
- fscanf (F,"%s",Path);
- pclose (F);
- #else
- extern char *getwd();
- if (!getwd (Path)) return 0;
- #endif /* S9000 */
- #endif /* PCAT */
-
- #if OPSYS==MSDOS
- (void) strcpy (Path,Path+2); /* Delete drive name */
- if (Debug & DebugFile) printf ("CWD = '%s'\n",Path);
- return 1;
- #endif
- #if OPSYS==UNIX
- {
- register int K;
- K = strlen (RootPath);
- if (strncmp (Path,RootPath,K)) return 0;
- else {
- (void) strcpy (Path,&Path[K]); /* Remove FP root path prefix */
- return 1;
- }
- }
- #endif
- }
- #endif /* OPSYS != CTSS */
-
- /*
- * InitFile
- *
- * The DOS version is kludgy. The problem is that DOSfopen changes
- * the current directory, thus munging it before CWDGet is called.
- */
- #if OPSYS==UNIX || OPSYS==CTSS
- void InitFile ()
- #endif
- #if OPSYS==MSDOS
- void InitFile (CWD)
- char *CWD;
- #endif
- {
- Object X;
- InDesc F;
-
- if (Debug & DebugFile) printf ("enter InitFile\n");
- #if OPSYS!=CTSS
- EnvGet ("EDITOR",EditorPath,MAXPATH);
- #endif
- if (Debug & DebugFile) printf ("EditorPath = `%s'\n",EditorPath);
- #if OPSYS==UNIX
- EdCommand = PathTail (EditorPath);
- if (!*EdCommand) {
- fprintf (stderr,"\n * EDITOR environment variable not a full path.");
- fprintf (stderr,"\n Setting editor to '%s'.\n",EDITOR);
- EdCommand = PathTail (strcpy (EditorPath,EDITOR));
- }
- EnvGet ("IFPprompt",FPprompt,sizeof (FPprompt));
- #endif
- #if OPSYS==MSDOS
- EnvGet ("IFPDIR",DirPath,MAXPATH);
- if (Debug & DebugFile) printf ("IFPDIR = '%s'\n",DirPath);
- #endif
-
- /* Create dummy descriptor for scanning environment info */
- InitIn (&F,(NodePtr) NULL,(FILE *) NULL, -1);
-
- #if OPSYS==UNIX
- if (!CWDGet (F.InBuf,INBUFSIZE-1)) {
- fprintf (stderr,"\n\n * Current directory not a IFP subdirectory.");
- fprintf (stderr, "\n Setting current directory to IFP root.\n");
- if (chdir (RootPath)) {
- extern int errno;
- perror (RootPath);
- exit (errno);
- } else F.InBuf[0] = '\0';
- }
- #endif
- #if OPSYS==MSDOS
- {
- register char *T;
- (void) strcpy (F.InBuf,CWD);
- for (T=F.InBuf; *T; T++)
- if (*T == PATH_SEPARATOR) *T = '/';
- }
- #endif
- #if OPSYS==CTSS
- (void) strcpy (F.InBuf,USER_PATH);
- #endif
- if (F.InBuf[0]) {
- (void) strcat (F.InPtr,"\n");
- (void) InNode (&F,&X,NIL);
- CurWorkDir = MakeNode (X.List,1);
- } else
- CurWorkDir = RootNode;
- if (Debug & DebugFile) printf ("exit InitFile\n");
- }
-
-
- /************************* end of file.c *******************************/
-
- SHAR_EOF
- if test -f 'interp/forms.c'
- then
- echo shar: over-writing existing file "'interp/forms.c'"
- fi
- cat << \SHAR_EOF > 'interp/forms.c'
-
- /****** forms.c *******************************************************/
- /** **/
- /** University of Illinois **/
- /** **/
- /** Department of Computer Science **/
- /** **/
- /** Tool: IFP Version: 0.5 **/
- /** **/
- /** Author: Arch D. Robison Date: May 1, 1985 **/
- /** **/
- /** Revised by: Arch D. Robison Date: July 28, 1986 **/
- /** **/
- /** Principal Investigators: Prof. R. H. Campbell **/
- /** Prof. W. J. Kubitz **/
- /** **/
- /** **/
- /**------------------------------------------------------------------**/
- /** (C) Copyright 1987 University of Illinois Board of Trustees **/
- /** All Rights Reserved. **/
- /**********************************************************************/
-
- #include "struct.h"
- #include "node.h"
- #include "umax.h"
- #include "stats.h"
- #include <stdio.h>
-
- /*
- * FF_Each
- *
- * Apply function F to each element of list InOut
- *
- * Input
- * InOut = list of elements to apply function
- * Funs = singleton list of function to be applied
- *
- * Output
- * InOut = result
- */
- private FF_Each (InOut,Funs)
- ObjectPtr InOut;
- register ListPtr Funs;
- {
- register ListPtr P;
-
- switch (InOut->Tag) {
- default:
- FormError (InOut,ArgNotSeq,NODE_Each,Funs);
- return;
- case LIST:
- CopyTop (&InOut->List);
- break;
- }
- for (P = InOut->List; P!=NULL; P=P->Next) {
- Apply (&P->Val,&Funs->Val);
- if (P->Val.Tag == BOTTOM) {
- RepTag (InOut,BOTTOM); /* Error already reported */
- return;
- }
- }
- }
-
-
- /*
- * FF_Filter
- *
- * Input
- * InOut = list of elements to apply predicate
- * Funs = singleton list of function to be applied
- *
- * Output
- * InOut = result - list of element for which predicate is true.
- */
- private FF_Filter (InOut,Funs)
- register ObjectPtr InOut;
- register ListPtr Funs;
- {
- register ListPtr P;
- register MetaPtr E;
- ListPtr Result;
- Object X;
-
- if (InOut->Tag != LIST)
- FormError (InOut,ArgNotSeq,NODE_Filter,Funs);
- else {
- Result = NULL;
- E = &Result;
- for (P = InOut->List; P!=NULL; P=P->Next) {
- CopyObject (&X,&P->Val);
- Apply (&X,&Funs->Val);
- if (X.Tag != BOOLEAN) {
- FormError (&X,"non-boolean predicate",NODE_Filter,Funs);
- RepTag (InOut,BOTTOM);
- DelLPtr (Result);
- return;
- } else if (X.Bool) { /* append element to result list */
- NewList (E,1L);
- CopyObject (&(*E)->Val,&P->Val);
- E = &(*E)->Next;
- }
- }
- DelLPtr (InOut->List);
- InOut->List = Result;
- }
- }
-
-
- /*
- * FF_Compose
- *
- * Function composition
- *
- * Input
- * InOut = object to apply composition
- * Funs = list of functions to compose in reverse order
- *
- * Output
- * InOut = result of composition
- */
- private FF_Compose (InOut,Funs)
- register ObjectPtr InOut;
- register ListPtr Funs;
- {
- for (; Funs != NULL && InOut->Tag != BOTTOM; Funs = Funs->Next)
- Apply (InOut,&Funs->Val);
- }
-
- /*
- * FF_RInsert
- *
- * Function right insert
- */
- private FF_RInsert (InOut,Funs)
- register ObjectPtr InOut;
- register ListPtr Funs;
- {
- ListPtr Terms;
-
- if (InOut->Tag != LIST)
- FormError (InOut,ArgNotSeq,NODE_RInsert,Funs);
- else if (InOut->List == NULL)
- FormError (InOut,"empty sequence",NODE_RInsert,Funs);
- else {
- F_Reverse (InOut); /* Copy top and reverse */
- Terms = InOut->List->Next;
- InOut->List->Next = NULL;
- RepObject (InOut,&InOut->List->Val);
- while (Terms != NULL) {
- /* form pair and apply function */
- NewList (&Terms->Next,1L);
- Terms->Next->Val.Tag = InOut->Tag;
- Terms->Next->Val.Data = InOut->Data;
- InOut->Tag = LIST;
- InOut->List = NULL;
- Rot3 (&InOut->List,&Terms,&Terms->Next->Next);
- Apply (InOut,&Funs->Val);
- if (InOut->Tag == BOTTOM) {
- DelLPtr (Terms);
- break;
- }
- }
- }
- }
-
- /*
- * FF_C
- *
- * Constant function
- */
- private FF_C (InOut,Funs)
- ObjectPtr InOut;
- register ListPtr Funs;
- {
- Stat (StatConstant (InOut));
- if (Funs == NULL)
- FormError (InOut,"(constant bottom)",NODE_C,Funs);
- else
- RepObject (InOut,&Funs->Val);
- }
-
- /*
- * FF_Out
- *
- * Print debugging message
- */
- private FF_Out (InOut,Funs)
- ObjectPtr InOut;
- register ListPtr Funs;
- {
- LineWait ();
- OutObject (&Funs->Val),
- printf (": "),
- OutObject (InOut),
- printf ("\n");
- LineSignal ();
- }
-
-
- #if FETCH
- /*
- * FF_Fetch
- *
- * Fetch form
- */
- private FF_Fetch (InOut,Funs)
- ObjectPtr InOut;
- register ListPtr Funs;
- {
- register ListPtr P,Q,R;
-
- if (InOut->Tag != LIST)
- FormError (InOut,ArgNotSeq,NODE_Fetch,Funs);
- else {
- R = NULL;
-
- for (P = InOut->List; P != NULL; P=P->Next)
- if (P->Val.Tag != LIST || (Q=P->Val.List) == NULL ||
- Q->Next == NULL || Q->Next->Next != NULL) {
- FormError (InOut,"element not a pair",NODE_Fetch,Funs);
- return;
- } else
- if (R == NULL && ObEqual (&Q->Val,&Funs->Val)) R = Q;
-
- if (R!=NULL) RepObject (InOut,&R->Next->Val);
- else FormError (InOut,"key not found",NODE_Fetch,Funs);
- return;
-
- }
- }
- #endif FETCH
-
-
- /*
- * FF_If
- *
- * Conditional p->f;g
- *
- * Input
- * InOut = object to apply conditional
- * Funs = <p f g>
- *
- * Output
- * InOut = result of conditional
- */
- private FF_If (InOut,Funs)
- ObjectPtr InOut;
- ListPtr Funs;
- {
- Object P;
-
- CopyObject (&P,InOut);
- Apply (&P,&Funs->Val);
- if (P.Tag == BOOLEAN)
- Apply (InOut, & (P.Bool ? Funs : Funs->Next)->Next->Val);
- else {
- FormError (&P,"non-boolean predicate",NODE_If,Funs);
- RepTag (InOut,BOTTOM);
- }
- }
-
- /*
- * FF_Construct
- *
- * Function construction
- *
- * Input
- * InOut = object to apply construction
- * Funs = list of functions to construct
- *
- * Output
- * InOut = result
- */
- private FF_Construct (InOut,Funs)
- register ObjectPtr InOut;
- ListPtr Funs;
- {
- register ListPtr P,F;
- Stat (StatConstruct (Funs));
- P = Repeat (InOut, ListLength (F = Funs));
- if (SysError) return;
- RepTag (InOut,LIST);
- for (InOut->List = P; F != NULL; P=P->Next,F=F->Next) {
- Apply (& P->Val,& F->Val);
- if (P->Val.Tag == BOTTOM) {
- RepTag (InOut,BOTTOM); /* Error was already reported */
- return;
- }
- }
- }
-
-
- /*
- * FF_Select
- *
- * Selector form (e.g. 1,2r)
- *
- * Input
- * InOut = object
- * Funs = index parameter list - positive values are left selectors
- * negative values are right selectors
- */
- private FF_Select (InOut,Funs)
- ObjectPtr InOut;
- ListPtr Funs;
- {
- register ListPtr P;
- register long N;
- char *E;
-
- N = Funs->Val.Int;
- switch (InOut->Tag) {
- default:
- E = ArgNotSeq;
- break;
- case NODE:
- NodeExpand (InOut);
-
- case LIST:
- P = InOut->List;
- if (N < 0) N += ListLength (P) + 1;
- if (--N >= 0) {
- for (; P!=NULL; P=P->Next)
- if (--N < 0) {
- RepObject (InOut,&P->Val);
- return;
- }
- E = "index off right end";
- } else
- E = "index off left end";
- break;
- }
- FormError (InOut,E,NODE_Sel,Funs);
- }
-
-
- /*
- * FF_While
- *
- * While P is true, apply F to X
- *
- * Input
- * InOut = X
- * Funs = pair <P F>
- *
- * Output
- * InOut = result
- */
- private FF_While (InOut,Funs)
- register ObjectPtr InOut;
- register ListPtr Funs;
- {
- Object P;
-
- P.Tag = BOTTOM;
- while (InOut->Tag!=BOTTOM) {
- CopyObject (&P,InOut); /* old P was element of {?,f,t} */
- Apply (&P,&Funs->Val);
- if (P.Tag != BOOLEAN) {
- FormError (&P,"non-boolean predicate",NODE_While,Funs);
- RepTag (InOut,BOTTOM);
- } else
- if (P.Bool) Apply (InOut,&Funs->Next->Val);
- else break;
- }
- }
-
-
- #if XDEF
- extern FF_XDef();
- #endif
-
- /*
- * FormTable
- *
- * These entries must be ordered to correspond with the #defines in "node.h".
- */
- FormEntry FormTable[] = {
- {NULL, "#", {"constant" ,-1,FF_C }, "#c"},
- {NULL, "", {"compose" ,-1,FF_Compose }, ""},
- {NULL, "[", {"construct",-1,FF_Construct}, "[...]"},
- {NULL, "EACH", {"each" , 1,FF_Each }, "EACH g END"},
- #if FETCH
- {NULL, "^", {"fetch" , 1,FF_Fetch }, "^c"},
- #endif
- {NULL, "FILTER", {"filter" , 1,FF_Filter }, "FILTER p END"},
- {NULL, "IF", {"if" , 3,FF_If }, "IF p THEN g ELSE h END"},
- {NULL, "INSERT", {"insertr" , 1,FF_RInsert }, "INSERT g END"},
- {NULL, "@", {"out" , 1,FF_Out }, "@message"},
- {NULL, "", {"select" , 1,FF_Select }, "digit"},
- {NULL, "WHILE", {"while" , 2,FF_While }, "WHILE p DO g END"}
- #if XDEF
- ,{NULL, "{", {"xdef" , 3,FF_XDef }, "{...}"},
- #endif
- };
-
- void D_form ()
- {
- FormEntry *N;
-
- for (N=FormTable; N<ArrayEnd (FormTable); N++)
- N->FormNode = PrimDef (N->FormOp.OpPtr,
- N->FormOp.OpName,
- SysNode,
- N->FormOp.OpParam);
- }
-
- /******************************* end of forms.c *******************************/
-
- SHAR_EOF
- # End of shell archive
- exit 0
-
- --
-
- Rich $alz "Anger is an energy"
- Cronus Project, BBN Labs rsalz@pineapple.bbn.com
- Moderator, comp.sources.unix sources@uunet.uu.net
-